/*
Copyright (C) 1996-1997 Id Software, Inc.

This program is free software; you can redistribute it and/or
modify it under the terms of the GNU General Public License
as published by the Free Software Foundation; either version 3
of the License, or (at your option) any later version.

This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.

See the GNU General Public License for more details.

You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.

*/
// disable data conversion warnings

#pragma once

extern ID3D10Device *d3d_Device;
extern IDXGISwapChain *d3d_SwapChain;

extern QTEXTURE d3d_RenderTarget;
extern QTEXTURE d3d_DepthBuffer;

#include "d3d_state.h"

BOOL GL_BeginRendering (void);
void GL_EndRendering (void);


// r_local.h -- private refresh defs
void R_AnimateLight (double time);
void R_InitializeLightStyles (void);

#define ALIAS_BASE_SIZE_RATIO		(1.0 / 11.0)
// normalizing factor so player model works out to about
//  1 pixel per triangle

#define BACKFACE_EPSILON	0.01


void R_TimeRefresh_f (void);
void R_ReadPointFile_f (void);

//====================================================

extern	entity_t	r_worldentity;

extern	int		c_brush_polys, c_alias_polys;
extern	int		c_draw_call;


// screen size info
extern	refdef_t	ref;
extern	texture_t	r_notexture_mip;

extern	float	d_lightstylevalue[];	// 8.8 fraction of base light value

void R_VisReset (void);

typedef struct playertexture_s
{
	int Width;
	int Height;
	int Top;
	int Bottom;
	QTEXTURE *Texture;
} playertexture_t;

extern playertexture_t PlayerTextures[];

extern cvar_t *r_norefresh;
extern cvar_t *r_drawentities;
extern cvar_t *r_drawviewmodel;
extern cvar_t *r_speeds;
extern cvar_t *r_fullbright;
extern cvar_t *r_lightmap;
extern cvar_t *r_lightscale;
extern cvar_t *r_shadows;
extern cvar_t *r_wateralpha;
extern cvar_t *r_dynamic;
extern cvar_t *r_novis;
extern cvar_t *r_draworder;
extern cvar_t *r_lockpvs;
extern cvar_t *r_lockfrustum;
extern cvar_t *r_clearcolor;
extern cvar_t *gl_finish;
extern cvar_t *gl_clear;
extern cvar_t *gl_cull;
extern cvar_t *gl_polyblend;
extern cvar_t *gl_nocolors;
extern cvar_t *gl_doubleeyes;
extern cvar_t *gl_texture_anisotropy;
extern cvar_t *r_batchmode;
extern cvar_t *r_showbboxes;
extern cvar_t *r_particle_size;
extern cvar_t *r_realtime_lighting;
extern cvar_t *r_shadowmapdepthbias;

void R_InitParticles (void);
void R_TranslatePlayerSkin (int playernum);
void R_Clear (void);
BOOL R_CheckWaterWarp (void);


#define VDECL(name, index, fmt, slot, steprate) \
{ \
	name, \
	index, \
	fmt, \
	slot, \
	D3D10_APPEND_ALIGNED_ELEMENT, \
	((steprate > 0) ? D3D10_INPUT_PER_INSTANCE_DATA : D3D10_INPUT_PER_VERTEX_DATA), \
	steprate \
}

extern int r_RegistrationSequence;

#define TEX_MIPMAP			1
#define TEX_ALPHA			2
#define TEX_LUMA			4
#define TEX_NODISCARD		8
#define TEX_32BIT			16
#define TEX_BGRA			32
#define TEX_CUBEMAP			64
#define TEX_IMMUTABLE		128
#define TEX_RENDERTARGET	256
#define TEX_DEPTHBUFFER		512
#define TEX_NOSRV			1024

// image operations
typedef struct imagedata_s
{
	int width;
	int height;
	byte *data;
} imagedata_t;

imagedata_t *Image_LoadImageFile (char *basename, imagedata_t *image);
unsigned *GL_MipMap (unsigned *in, int width, int height);
unsigned *GL_ResampleTexture (unsigned *in, int inwidth, int inheight, int outwidth, int outheight);
unsigned *R_MipMap (unsigned *trans, int &Width, int &Height);
unsigned *R_ExpandTexture (byte *Data, int Width, int Height, int Flags);
void R_SetupSRD (D3D10_SUBRESOURCE_DATA *srd, unsigned *trans, int Width);
D3D10_SUBRESOURCE_DATA *R_CreateTextureSRDs (byte *Data, int Width, int Height, int ArraySize, int MipLevels, int Flags);

QTEXTURE *D3D_LoadTexture (char *Identifier, byte *Data, int Width, int Height, int Flags);
QTEXTURE *D3D_ScrapUpload (int width, int height, byte *data, int &scrap_x, int &scrap_y);

// these are also used by the game system so they're declared separately too
void D3D_FreeUnusedTextures (void);
void Tex_Shutdown (void);
void Tex_Init (void);

// helpers/etc
void D3D_CollapseRowPitch (unsigned *data, int width, int height, int pitch);
void D3D_Compress32To24WithSwapToBGR (byte *out, byte *in, int width, int height);
void D3D_CollapseRowPitchWith32To24 (unsigned *data, int width, int height, int pitch);
void D3D_WriteDataToTGA (char *name, void *data, int width, int height, int bpp);
void D3D_WriteDataToTGAWithPitchCollapseAnd32To24 (char *name, unsigned *data, int width, int height, int pitch);

// needs to be common
#define SCRAP_SIZE		256
#define MAPSHOT_SIZE	128


typedef enum {handler_init, handler_shutdown, handler_resetdevice, handler_lostdevice, handler_modechange, hander_perframe} vidhandlertype_t;

/*
class <handlerName> : public CD3DHandler
{
public:
	void OnCreateDevice (void) {}
	void OnReleaseDevice (void) {}
	void OnModeChange (void) {}
	void OnBeginFrame (void) {}
	void OnResetDevice (void) {}
	void OnLostDevice (void) {}
};
*/

class CD3DHandler
{
public:
	CD3DHandler (void);

	virtual void OnCreateDevice (void) {}
	virtual void OnReleaseDevice (void) {}
	virtual void OnModeChange (void) {}
	virtual void OnBeginFrame (void) {}
	virtual void OnLostDevice (void) {}
	virtual void OnResetDevice (void) {}
};


void VID_RunHandlers (vidhandlertype_t type);

void R_PrepareWaterWarp (void);
void R_FinishWaterWarp (void);
QTEXTURE *D3D_CaptureScreen (void);

BOOL R_CullBox (mplane_t *frustum, float *mins, float *maxs, int clipflags);
BOOL R_CullSphere (float *center, float radius, int clipflags);

void Mod_BBoxFromSphere (const float *center, float radius, float *mins, float *maxs);
void Mod_NewPositionFromBBox (float *newposition, const float *oldposition, const float *bbmins, const float *bbmaxs);
BOOL Mod_SphereBoxCollide (float *bmins, float *bmaxs, float *bmids, float *sorigin, float sradius);

void Mod_ClearBBox (float *mins, float *maxs);
void Mod_AccumulateBBox (float *point, float *mins, float *maxs);
void Mod_AccumulateBBox2 (float *pmins, float *pmaxs, float *mins, float *maxs);
void Mod_ComputeBBox (const QMATRIX *matrix, const float *boxmins, const float *boxmaxs, float *emins, float *emaxs);
void Mod_ComputeAliasBBox (entity_t *e, aliashdr_t *hdr, float *emins, float *emaxs);
void Mod_GetBBoxCenter (float *mids, const float *mins, const float *maxs, float frac = 0.5f);

// all the stuff that's created on map load
void R_ClearParticles (void);
void GL_BuildBrushSurfaces (void);
void Sprite_CreateBuffers (void);
void GL_MakeAliasModelDisplayLists (aliashdr_t *hdr, stvert_t *stverts, dtriangle_t *triangles);
void R_LoadMeshBuffers (void);

// model draw funcs
void R_MarkLeaves (void);
void R_DrawWorld (void);
void R_DrawAliasModel (entity_t *e);
void R_DrawBrushModel (entity_t *e);
void R_AddSpriteToAlphaList (entity_t *e);
void R_DrawSpriteModel (entity_t *e);
void R_RunParticleEmitters (void);
void R_SetupSurfaceDrawState (entity_t *e, model_t *m, float alpha = 1.0f);
void R_ShowBBoxes (void);
void R_DrawBoundingBox (const float *mins, const float *maxs, const float *shadelight);

// alpha objects
typedef void (*alphaobjectdrawfunc_t) (void *);

void R_AddAlphaObject (void *object, float *origin, xcommand_t BeginFunc, alphaobjectdrawfunc_t DrawFunc, xcommand_t EndFunc);
void R_DrawAlphaObjects (void);

void R_AddAlphaSurface (entity_t *ent, msurface_t *surf, float alpha);
void R_NewAlphaSurfaces (void);

extern D3D10_FILTER d3d_MinMagMipFilter;
extern DWORD d3d_Anisotropy;

void D3D_HandleDeviceReset (void);
void D3D_HandleLostDevice (void);
void D3D_VidChangeMode (DXGI_MODE_DESC *mode, BOOL windowed);

// shader compiler
ID3D10VertexShader *D3D_CreateVertexShader (int resourceID, const char *entrypoint, const char *customdefine = NULL);
ID3D10PixelShader *D3D_CreatePixelShader (int resourceID, const char *entrypoint, const char *customdefine = NULL);


void Sky_LoadSkyBox (char *name);
void Sky_ClearSkybox (void);
void Sky_NewMap (void);
void Sky_LoadSkyBox_f (void);


extern QTEXTURE d3d_WhiteTexture;
extern QTEXTURE d3d_GreyTexture;
extern QTEXTURE d3d_BlackTexture;
extern QTEXTURE d3d_NoTextureMip;
extern QTEXTURE PaletteRowTextures[];

void RGBToYCoCg (float *rgb);
void YCoCgToRGB (float *c);

void Mesh_ShutdownBuffers (void);

void GL_BeginBuildingLightmaps (void);
void GL_CreateSurfaceLightmap (msurface_t *surf);
void GL_EndBuildingLightmaps (void);

void R_DrawDynamicLights (struct entity_t *e);
void R_GatherLights (void);
void R_SwitchToGBuffer (void);
void R_DrawRealtimeScene (entity_t **entities, int numentities);

void Fog_SetupFrame (void);
void Fog_SetEyePosition (QMATRIX &m);
void Fog_Init (void);
void Fog_NewMap (void);

// these are our common buffer slots that we ensure everything is bound to
#define BUFFER_SLOT_DRAW		3
#define BUFFER_SLOT_SURFACES	4
#define BUFFER_SLOT_SPRITES		5
#define BUFFER_SLOT_PARTICLES	6
#define BUFFER_SLOT_LIGHTS		7
#define BUFFER_SLOT_LVOLUME		8

// and these are our common texture slots
#define TEXTURE_SLOT_SPRITES	3
#define TEXTURE_SLOT_SOLIDSKY	6
#define TEXTURE_SLOT_ALPHASKY	7
#define TEXTURE_SLOT_CUBESKY	8
#define TEXTURE_SLOT_SURFACES	9
#define TEXTURE_SLOT_LIGHTMAP0	10
#define TEXTURE_SLOT_LIGHTMAP1	11
#define TEXTURE_SLOT_LIGHTMAP2	12
#define TEXTURE_SLOT_LIGHTMAP3	13
#define TEXTURE_SLOT_GBUFFER1	14
#define TEXTURE_SLOT_GBUFFER2	15
#define TEXTURE_SLOT_GBUFFER3	16
#define TEXTURE_SLOT_GBUFFER4	17
#define TEXTURE_SLOT_SHADOW		18

// define some input layout types (these must match the order in r_shader.cpp)
#define INPUT_LAYOUT_NONE		-1
#define INPUT_LAYOUT_SURF		0
#define INPUT_LAYOUT_MESH		1
#define INPUT_LAYOUT_XYZ		2
#define INPUT_LAYOUT_WARP		3
#define INPUT_LAYOUT_SPRITE		4
#define INPUT_LAYOUT_DRAW		5
#define INPUT_LAYOUT_PART		6
#define INPUT_LAYOUT_LIGHT		7
#define INPUT_LAYOUT_SKY		8
#define INPUT_LAYOUT_MESHSV		9

// common vertex shader registers
enum vsregisters_t
{
	// a matrix is 4 registers
	VS_WORLDMATRIX,
	VS_LOCALMATRIX = 4,
	VS_ENTITYMATRIX = 8,
	VS_FORWARDVEC = 12,
	VS_UPVEC,
	VS_RIGHTVEC,
	VS_WARPTIME,
	VS_WARPSCALE,
	VS_WARPSPEED,
	VS_LERPBLEND,
	VS_GRAVITY,
	VS_PARTICLESIZE,
	VS_CURRENTSTYLE,
	VS_LIGHTORIGIN,
	VS_FOGCOLOUR,
	VS_FOGDENSITY,
	VS_EYEPOSITIONWORLD,
	VS_EYEPOSITIONLOCAL,

	// this comes last and the remaining VS regs are taken up by the light styles
	VS_LIGHTSTYLES
};


// common pixel shader registers
enum psregisters_t
{
	PS_ALPHA,
	PS_SHADELIGHT,
	PS_SHADEVECTOR,
	PS_LIGHTRADIUS,
	PS_DEPTHBIAS,
	PS_FOGCOLOUR,
	PS_SKYFOGDENSITY,
	PS_SKYSPEEDSCALE,
	PS_WARPFACTOR,
	PS_GAMMA
};


extern int current_lightmap_texture;

void R_AddLeafPVS (mleaf_t *viewleaf);

// shaders
struct QSHADER
{
	QSHADER (void);

	ID3D10VertexShader *VertexShader;
	ID3D10InputLayout *InputLayout;
	ID3D10GeometryShader *GeometryShader;
	ID3D10PixelShader *PixelShader;

	// it's no longer necessary to release shaders as the shader cache will auto-release them for me
	void CreateShaders (int resourceID, const char *vsentry, const char *gsentry, const char *psentry, int layout);
	void Bind (void);
};

// imports from r_surf and elsewhere for sharing with rt lights
BOOL R_ClipWorldNode (mnode_t *node, int &clipflags);
void R_HandleWorldLeaf (mleaf_t *leaf);
BOOL R_CullWorldSurface (msurface_t *surf, int clipflags, float dot);
void R_AnimateTextures (model_t *m, int frame);
void R_ChainSurface (msurface_t *surf, entity_t *e, float entalpha);
void R_DrawTextureChains (struct entity_t *e, float entalpha);
void R_AddRealtimeBrushModelSurfaces (entity_t *e);
void R_DrawEntitiesOnList (void);
texture_t *R_TextureAnimation (texture_t *base, int frame);
void R_MarkNodes (entity_t *e, mnode_t *node, msurface_t *surfaces);
void R_AddSurface (msurface_t *surf, texture_t *tex, entity_t *e, float entalpha);
void R_NewDrawTextureChains (struct entity_t *e);

void R_LoadRTLightsFromRTLights (void);
void R_LoadRTLightsFromBSPEntities (void);
void R_ReloadRTLights (void);
void R_DrawZFillSurfaces (texturechain_t *Chain);

// texture chain building
void R_CreateTextureChains (model_t *m);
void R_AddSurfaceToTextureChain (msurface_t *surf, texturechain_t *Chain, chaintype_t Type);
void R_AddSurfaceToTextureChain (msurface_t *surf, chaintype_t Type);
void R_ClearTextureChain (texturechain_t *Chain);

// and drawing
void R_DrawNewTextureChain (texture_t *tex, chaintype_t Type);
void R_DrawNewTextureChain (texturechain_t *Chain, chaintype_t Type);
void R_DrawLightmappedSurfaces (model_t *m, chaintype_t Type, int style, ID3D10BlendState *blendmode, ID3D10DepthStencilState *depthmode);
void R_DrawDeferredSurfaces (model_t *m);
void R_DrawUnlitSurfaces (model_t *m, int texnum, chaintype_t Type, ID3D10BlendState *blendmode, ID3D10DepthStencilState *depthmode);
void R_DrawGenericSurfaces (model_t *m, chaintype_t Type, int texnum, QSHADER *shader, ID3D10BlendState *blendmode, ID3D10DepthStencilState *depthmode);
void R_DrawWaterSurfaces (model_t *m);
void R_DrawSkyChain (texturechain_t *SkyChain);

// MDLs here too because we need them for dynamic and realtime lighting
void R_RenderAliasModel (entity_t *e, aliashdr_t *hdr, QSHADER *shader, ID3D10BlendState *blendmode, ID3D10DepthStencilState *depthmode);

// for shadowmaps
void R_SetupViewpoint (void);
void R_SetupGL (void);
void R_LoadRealtimeLight (void);

// entity setup
void R_SetupEntity (entity_t *e);
void R_SetupObjectConstants (entity_t *e, float alpha = 1.0f);
BOOL R_SetupAliasModel (entity_t *e);
BOOL R_SetupBrushModel (entity_t *e);

void R_SetupStaticAliasModel (entity_t *e);
void R_SetupStaticBrushModel (entity_t *e);

void R_BruteForceAliasModel (entity_t *e, QSHADER *shader, ID3D10BlendState *blendmode, ID3D10DepthStencilState *depthmode);
void R_DrawAliasLuma (entity_t *e);
void R_DrawAliasAdjacency (entity_t *e);

void R_FreeShaderCache (void);

// extra surfaces are picked up after the deferred pass is run
void R_ClearExtraSurfaces (void);
void R_AddExtraSurface (msurface_t *surf, entity_t *ent, texture_t *tex, chaintype_t type);
void R_HandleExtraSurfaces (void);


// geometric objects
struct geo_t
{
public:
	ID3D10Buffer *VertexBuffer;
	ID3D10Buffer *IndexBuffer;
	int NumVertexes;
	int NumIndexes;

	geo_t (void);
	void CreateSphere (void);
	void CreateIcosahedron (void);
	void CreateBox (void);
	void Release (void);

private:
	void CreateShape (const float *verts, int vertsize, const unsigned short *indexes, int indexsize);
};

#define MAX_ACTIVE_LIGHTS	(MAX_MAP_ENTITIES + MAX_DLIGHTS)

extern dlight_t r_realtimelights[];
extern int r_num_realtimelights;

extern dlight_t *r_activelights[];
extern int r_numactivelights;

void R_ClearShadowBuffer (int num);
void R_ClearShadowBuffers (void);
